/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _H_TOKEN_
#define _H_TOKEN_

#include <stdio.h>
#include <stdint.h>

#include "wbyte.h"

#define SINGLE_TO_TOKENTYPE(_c_)			( (uint32_t)(_c_)<<24 )
#define DOUBLE_TO_TOKENTYPE(_c1_,_c2_)			( ((uint32_t)(_c1_)<<24) | (uint32_t)(_c2_)<<16 )
#define TRIPLE_TO_TOKENTYPE(_c1_,_c2_,_c3_)		( ((uint32_t)(_c1_)<<24) | ((uint32_t)(_c2_)<<16) | (uint32_t)(_c3_)<<8 )
#define QUADRUPLE_TO_TOKENTYPE(_c1_,_c2_,_c3_,_c4_)	( ((uint32_t)(_c1_)<<24) | ((uint32_t)(_c2_)<<16) | ((uint32_t)(_c3_)<<8) | (uint32_t)(_c4_) ) 

#define TOKENTYPE_TO_STRING(_i_,_str_)			{ (_str_)[0]=(((_i_)>>24)&0xFF); (_str_)[1]=(((_i_)>>16)&0xFF); (_str_)[2]=(((_i_)>>8)&0xFF); (_str_)[3]=((_i_)&0xFF); }

enum TokenType
{
	TOKEN_TYPE_NONE = 0 ,
	TOKEN_TYPE_END_OF_SOURCE = 1 ,
	
	TOKEN_TYPE_PART_OF_STATEMENT = SINGLE_TO_TOKENTYPE(',') ,
	TOKEN_TYPE_END_OF_STATEMENT = SINGLE_TO_TOKENTYPE(';') ,
	TOKEN_TYPE_MEMBER_OF = SINGLE_TO_TOKENTYPE('.') ,
	TOKEN_TYPE_ETC = TRIPLE_TO_TOKENTYPE('.','.','.') ,
	TOKEN_TYPE_DOUBLE_QUOTES_STRING = QUADRUPLE_TO_TOKENTYPE('D','S','T','R') ,
	TOKEN_TYPE_TRIPLE_QUOTES_STRING = QUADRUPLE_TO_TOKENTYPE('T','S','T','R') ,
	TOKEN_TYPE_TRIPLE_BACK_QUOTES_STRING = QUADRUPLE_TO_TOKENTYPE('T','B','S','T') ,
	TOKEN_TYPE_OPERATOR_PLUS = SINGLE_TO_TOKENTYPE('+') ,
	TOKEN_TYPE_OPERATOR_MINUS = SINGLE_TO_TOKENTYPE('-') ,
	TOKEN_TYPE_OPERATOR_MUL = SINGLE_TO_TOKENTYPE('*') ,
	TOKEN_TYPE_OPERATOR_DIV = SINGLE_TO_TOKENTYPE('/') ,
	TOKEN_TYPE_OPERATOR_MOD = SINGLE_TO_TOKENTYPE('%') ,
	TOKEN_TYPE_OPERATOR_PLUS_PLUS = DOUBLE_TO_TOKENTYPE('+','+') ,
	TOKEN_TYPE_OPERATOR_MINUS_MINUS = DOUBLE_TO_TOKENTYPE('-','-') ,
	TOKEN_TYPE_REFER = SINGLE_TO_TOKENTYPE('=') ,
	TOKEN_TYPE_EVAL = DOUBLE_TO_TOKENTYPE('=','*') ,
	TOKEN_TYPE_CAST_REFER = DOUBLE_TO_TOKENTYPE('=','&') ,
	TOKEN_TYPE_EQUAL = DOUBLE_TO_TOKENTYPE('=','=') ,
	TOKEN_TYPE_NOT_EQUAL = DOUBLE_TO_TOKENTYPE('!','=') ,
	TOKEN_TYPE_REFER_EQUAL = TRIPLE_TO_TOKENTYPE('=','=','&') ,
	TOKEN_TYPE_REFER_NOT_EQUAL = TRIPLE_TO_TOKENTYPE('!','=','&') ,
	TOKEN_TYPE_ANCESTOR_EQUAL = TRIPLE_TO_TOKENTYPE('=','=',':') ,
	TOKEN_TYPE_ANCESTOR_NOT_EQUAL = TRIPLE_TO_TOKENTYPE('!','=',':') ,
	TOKEN_TYPE_COMPARE_LT = SINGLE_TO_TOKENTYPE('<') ,
	TOKEN_TYPE_COMPARE_LE = DOUBLE_TO_TOKENTYPE('<','=') ,
	TOKEN_TYPE_COMPARE_GT = SINGLE_TO_TOKENTYPE('>') ,
	TOKEN_TYPE_COMPARE_GE = DOUBLE_TO_TOKENTYPE('>','=') ,
	TOKEN_TYPE_LOGIC_AND = DOUBLE_TO_TOKENTYPE('&','&') ,
	TOKEN_TYPE_LOGIC_OR = DOUBLE_TO_TOKENTYPE('|','|') ,
	TOKEN_TYPE_BIT_AND = SINGLE_TO_TOKENTYPE('&') ,
	TOKEN_TYPE_BIT_XOR = SINGLE_TO_TOKENTYPE('^') ,
	TOKEN_TYPE_BIT_OR = SINGLE_TO_TOKENTYPE('|') ,
	TOKEN_TYPE_BIT_REVERSE = SINGLE_TO_TOKENTYPE('~') ,
	TOKEN_TYPE_BIT_MOVELEFT = DOUBLE_TO_TOKENTYPE('<','<') ,
	TOKEN_TYPE_BIT_MOVERIGHT = DOUBLE_TO_TOKENTYPE('>','>') ,
	TOKEN_TYPE_NOT = SINGLE_TO_TOKENTYPE('!') ,
	TOKEN_TYPE_REFER_VALUE = TOKEN_TYPE_BIT_AND ,
	TOKEN_TYPE_OPERATOR_PLUS_EVAL = DOUBLE_TO_TOKENTYPE('+','=') ,
	TOKEN_TYPE_OPERATOR_MINUS_EVAL = DOUBLE_TO_TOKENTYPE('-','=') ,
	TOKEN_TYPE_OPERATOR_MUL_EVAL = DOUBLE_TO_TOKENTYPE('*','=') ,
	TOKEN_TYPE_OPERATOR_DIV_EVAL = DOUBLE_TO_TOKENTYPE('/','=') ,
	TOKEN_TYPE_OPERATOR_MOD_EVAL = DOUBLE_TO_TOKENTYPE('%','=') ,
	TOKEN_TYPE_BIT_AND_EVAL = DOUBLE_TO_TOKENTYPE('&','=') ,
	TOKEN_TYPE_BIT_XOR_EVAL = DOUBLE_TO_TOKENTYPE('|','=') ,
	TOKEN_TYPE_BIT_OR_EVAL = DOUBLE_TO_TOKENTYPE('^','=') ,
	TOKEN_TYPE_BIT_MOVELEFT_EVAL = TRIPLE_TO_TOKENTYPE('<','<','=') ,
	TOKEN_TYPE_BIT_MOVERIGHT_EVAL = TRIPLE_TO_TOKENTYPE('>','>','=') ,
	TOKEN_TYPE_BEGIN_OF_SUB_EXPRESSION = SINGLE_TO_TOKENTYPE('(') ,
	TOKEN_TYPE_END_OF_SUB_EXPRESSION = SINGLE_TO_TOKENTYPE(')') ,
	TOKEN_TYPE_BEGIN_OF_ARRAY = SINGLE_TO_TOKENTYPE('[') ,
	TOKEN_TYPE_END_OF_ARRAY = SINGLE_TO_TOKENTYPE(']') ,
	TOKEN_TYPE_BEGIN_OF_STATEMENT_SEGMENT = SINGLE_TO_TOKENTYPE('{') ,
	TOKEN_TYPE_END_OF_STATEMENT_SEGMENT = SINGLE_TO_TOKENTYPE('}') ,
	
	TOKEN_TYPE_JUDGE = SINGLE_TO_TOKENTYPE('?') , /* ? */
	TOKEN_TYPE_ANOTHER_SIDE = SINGLE_TO_TOKENTYPE(':') , /* : */
	
	TOKEN_TYPE_TRUE = QUADRUPLE_TO_TOKENTYPE('T','R','U','E') , /* true */
	TOKEN_TYPE_FALSE = QUADRUPLE_TO_TOKENTYPE('F','A','L','S') , /* false */
	TOKEN_TYPE_NULL = QUADRUPLE_TO_TOKENTYPE('N','U','L','L') , /* null */
	
#if 0
	TOKEN_TYPE_SWITCH = QUADRUPLE_TO_TOKENTYPE('S','W','I','T') , /* ?? */
	TOKEN_TYPE_SWITCH_CASE = TOKEN_TYPE_IF , /* ? */
	TOKEN_TYPE_SWITCH_DEFAULT = QUADRUPLE_TO_TOKENTYPE('S','W','D','F') , /* :: */
	TOKEN_TYPE_FOR = TRIPLE_TO_TOKENTYPE('F','O','R') , /* @ */
	TOKEN_TYPE_FOR_TO = QUADRUPLE_TO_TOKENTYPE('F','O','R','T') , /* ~ */
	TOKEN_TYPE_FOR_IN = QUADRUPLE_TO_TOKENTYPE('F','O','R','I') , /* ~~ */
#endif
	TOKEN_TYPE_CHARSET = QUADRUPLE_TO_TOKENTYPE('C','H','S','T') , /* charset */
	TOKEN_TYPE_INCLUDE = QUADRUPLE_TO_TOKENTYPE('I','N','C','L') , /* include */
	
	TOKEN_TYPE_NEW = TRIPLE_TO_TOKENTYPE('N','E','W') , /* new */
	
	TOKEN_TYPE_IF = DOUBLE_TO_TOKENTYPE('I','F') , /* if */
	TOKEN_TYPE_ELSE = QUADRUPLE_TO_TOKENTYPE('E','L','S','E') , /* else */
	TOKEN_TYPE_SWITCH = QUADRUPLE_TO_TOKENTYPE('S','W','I','T') , /* switch */
	TOKEN_TYPE_CASE = QUADRUPLE_TO_TOKENTYPE('C','A','S','E') , /* case */
	TOKEN_TYPE_DEFAULT = QUADRUPLE_TO_TOKENTYPE('D','F','L','T') , /* default */
	TOKEN_TYPE_DO = DOUBLE_TO_TOKENTYPE('D','O') , /* do */
	TOKEN_TYPE_WHILE = QUADRUPLE_TO_TOKENTYPE('W','H','I','L') , /* while */
	TOKEN_TYPE_FOR = TRIPLE_TO_TOKENTYPE('F','O','R') , /* for */
	TOKEN_TYPE_IN = DOUBLE_TO_TOKENTYPE('I','N') , /* in */
	TOKEN_TYPE_FROM = QUADRUPLE_TO_TOKENTYPE('F','R','O','M') , /* from */
	TOKEN_TYPE_TO = DOUBLE_TO_TOKENTYPE('T','O') , /* to */
	TOKEN_TYPE_FOREACH = QUADRUPLE_TO_TOKENTYPE('F','O','R','E') , /* foreach */
	TOKEN_TYPE_CONTINUE = QUADRUPLE_TO_TOKENTYPE('C','O','N','T') , /* continue */
	TOKEN_TYPE_BREAK = QUADRUPLE_TO_TOKENTYPE('B','R','E','K') , /* break */
	
	TOKEN_TYPE_IMPORT = QUADRUPLE_TO_TOKENTYPE('I','M','P','T') , /* import */
	TOKEN_TYPE_FUNCTION = QUADRUPLE_TO_TOKENTYPE('F','U','N','C') , /* function */
	TOKEN_TYPE_OBJECT = TRIPLE_TO_TOKENTYPE('O','B','J') , /* object */
	TOKEN_TYPE_EXTENDS = QUADRUPLE_TO_TOKENTYPE('E','X','T','D') , /* extends */
	TOKEN_TYPE_INTERFACE = QUADRUPLE_TO_TOKENTYPE('I','T','F','C') , /* interface */
	TOKEN_TYPE_IMPLEMENTS = QUADRUPLE_TO_TOKENTYPE('I','M','P','E') , /* implements */
	TOKEN_TYPE_PUBLIC = TRIPLE_TO_TOKENTYPE('P','U','B') , /* public */
	TOKEN_TYPE_PRIVATE = TRIPLE_TO_TOKENTYPE('P','R','I') , /* private */
	TOKEN_TYPE_THIS = QUADRUPLE_TO_TOKENTYPE('T','H','I','S') , /* this */
	TOKEN_TYPE_INTERCEPT = QUADRUPLE_TO_TOKENTYPE('I','T','C','T') , /* intercept */
	TOKEN_TYPE_BEFORE = QUADRUPLE_TO_TOKENTYPE('B','E','F','R') , /* before */
	TOKEN_TYPE_AFTER = TRIPLE_TO_TOKENTYPE('A','F','T') , /* after */
	TOKEN_TYPE_SET = TRIPLE_TO_TOKENTYPE('S','E','T') , /* set */
	TOKEN_TYPE_GET = TRIPLE_TO_TOKENTYPE('G','E','T') , /* get */
#if 0
	TOKEN_TYPE_CLASS = QUADRUPLE_TO_TOKENTYPE('C','L','A','S') , /* class */
	TOKEN_TYPE_PROPERTY = QUADRUPLE_TO_TOKENTYPE('P','R','O','P') , /* prop */
#endif
	TOKEN_TYPE_DEFER = QUADRUPLE_TO_TOKENTYPE('R','E','F','R') , /* defer */
	TOKEN_TYPE_RETURN = QUADRUPLE_TO_TOKENTYPE('R','E','T','N') , /* return */
	TOKEN_TYPE_EXIT = QUADRUPLE_TO_TOKENTYPE('E','X','I','T') , /* exit */
	
	TOKEN_TYPE_SYNC = QUADRUPLE_TO_TOKENTYPE('S','Y','N','C') , /* sync */
	TOKEN_TYPE_ATOMIC = QUADRUPLE_TO_TOKENTYPE('A','T','O','M') , /* atomic */
	
	TOKEN_TYPE_NUMBER = TRIPLE_TO_TOKENTYPE('N','U','M') ,
	TOKEN_TYPE_FLOAT_NUMBER = QUADRUPLE_TO_TOKENTYPE('F','N','U','M') ,
	TOKEN_TYPE_IDENTIFICATION = QUADRUPLE_TO_TOKENTYPE('I','D','E','T') ,
	
	TOKEN_TYPE_SHORT_NUMBER = SINGLE_TO_TOKENTYPE('S') ,
	TOKEN_TYPE_USHORT_NUMBER = DOUBLE_TO_TOKENTYPE('U','S') ,
	TOKEN_TYPE_INT_NUMBER = SINGLE_TO_TOKENTYPE('I') ,
	TOKEN_TYPE_UINT_NUMBER = DOUBLE_TO_TOKENTYPE('U','I') ,
	TOKEN_TYPE_LONG_NUMBER = SINGLE_TO_TOKENTYPE('L') ,
	TOKEN_TYPE_ULONG_NUMBER = DOUBLE_TO_TOKENTYPE('U','L') ,
	TOKEN_TYPE_SINGLE_FLOAT_NUMBER = SINGLE_TO_TOKENTYPE('F') ,
	TOKEN_TYPE_DOUBLE_FLOAT_NUMBER = SINGLE_TO_TOKENTYPE('D') ,
	
	TOKEN_TYPE_CONST = QUADRUPLE_TO_TOKENTYPE('C','N','S','T') ,
	
	TOKEN_TYPE_ERROR = -2 ,
} ;

int EvaluateWbyteLength( uint16_t charset , unsigned char *begin , unsigned char *end );

enum TokenType TokenWord( uint16_t charset , char **source_offset_ptr , char *source_end , char **token_begin , int32_t *token_len , int32_t *source_row , int32_t *source_col );

#endif

